#!/bin/sh

function exit_when_request(){
	voff
	exit 0
}

function oct2cidr () {
	local mask bit cidr i
	mask=$1

	if grep -qv '\.' <<<$mask; then
		echo $mask
		return
	fi

	for i in 1 2 3 4; do
	bit=${bit}$(printf "%08d" \
	    $(echo 'ibase=10;obase=2;'$(cut -d '.' -f $i <<<$mask) |bc))
	done
	cidr=$(echo -n ${bit%%0*} |wc -m)

	echo $cidr
}

trap "exit_when_request" INT QUIT TERM

InstallDir=/usr/bin

cfile=/etc/vconfig
log_in=$InstallDir/vadsl_login
nfq=$InstallDir/vadsl_tnfq
nf_tables=nft

#检测是否为ROOT身份
uid=$(id -u)
if [ "$uid" != "0" ]
then
	echo 请以ROOT身份运行
	exit 1
fi

modinfo nft_queue > /dev/null
[ "$?" != "0" ] && echo "不支持的内核，未发现nft_queue模块" && exit 1

if [ -f $cfile ]
then
	echo 使用配置文件 $cfile
else
	echo 未找到配置文件 $cfile
	exit 1
fi

#参数提取
interface=$(sed -ne '/^#/d; s/\(interface\)\( \)\(.*\)/\3/p' $cfile)
bindip=$(sed -ne '/^#/d; s/\(bindip\)\( \)\(.*\)/\3/p' $cfile)
authserver=$(sed -ne '/^#/d; s/\(authserver\)\( \)\(.*\)/\3/p' $cfile)
account=$(sed -ne '/^#/d; s/\(account\)\( \)\(.*\)/\3/p' $cfile)
password=$(sed -ne '/^#/d; s/\(password\)\( \)\(.*\)/\3/p' $cfile)
threadsnum=$(sed -ne '/^#/d; s/\(threadsnum\)\( \)\(.*\)/\3/p' $cfile)
logfile=$(sed -ne '/^#/d; s/\(logfile\)\( \)\(.*\)/\3/p' $cfile)
echo 使用日志文件 $logfile
[ -z $interface ] || [ -z $bindip ] || [ -z $authserver ] || [ -z $account ] || [ -z $password ] || [ -z $logfile ] && echo 配置文件参数错误 && exit 1

#日志文件处理
[ -f $logfile ] && mv $logfile $logfile.last
touch $logfile

#开始发起认证
echo 开始发起认证
$log_in -i $interface -s $authserver -a $account -p $password -f $logfile -b $bindip &

#检测认证程序是否运行
loginpid=$(grep loginpid $logfile | cut -d':' -f5)
while [ -z $loginpid ]
do
	loginpid=$(grep loginpid $logfile | cut -d':' -f5)
done
#echo 登录进程号： $loginpid

#检测认证是否完成
authresult=$(grep AuthResult $logfile | cut -d':' -f5)
while [ -z $authresult ]
do
#检测认证程序是否正常运行
	if [ -z $(ps -eo pid | grep $loginpid) ]
	then
		authresult=$(grep AuthResult $logfile | cut -d':' -f5)
		[ -z $authresult ]  && echo 未进行认证，错误详情见日志文件 && exit 1
	fi
	authresult=$(grep AuthResult $logfile | cut -d':' -f5)
done
#echo 认证结果： $authresult

#检测认证结果
[ "$authresult" = "SUCCESS" ] || exit 1
#echo 认证成功

echo 设置 $interface 最大传输单元（MTU）大小为1476
ifconfig $interface mtu 1476

[ -z $threadsnum ] || threadsnum=2

#nftables设置
echo 开始设置nftables规则
$nf_tables add table vadsl-mangle
[ "$?" != "0" ] && echo "添加vadsl-mangle表失败" && voff && exit 1
$nf_tables add chain vadsl-mangle output {type route hook output priority 0\;}
$nf_tables add rule vadsl-mangle output ip daddr 127.0.0.0/8 accept
for rf in $(grep RF $logfile | cut -d':' -f2)
do
	network=`echo $rf | cut -d '/' -f1`
	netmask_dot=`echo $rf | cut -d '/' -f2`
	netmask_cidr=`oct2cidr $netmask_dot`
	[ -z $rf ] || $nf_tables add rule vadsl-mangle output ip daddr $network/$netmask_cidr accept
done
$nf_tables add rule vadsl-mangle output queue num 0 total $threadsnum options fanout,bypass
echo nftablesRulesSet >> $logfile
echo nftables规则已设置

#路由过滤进程
echo -n 正在启动路由过滤进程
relayip=$(grep RelayIP $logfile | cut -d':' -f2)
[ -z $relayip ] || nice --10 $nfq -d -b $bindip -r $relayip -f $logfile -t $threadsnum &

#检测路由过滤进程程序是否运行
nfqpid=$(grep nfqdpid $logfile | cut -d':' -f5)
while [ -z $nfqpid ]
do
	nfqpid=$(grep nfqdpid $logfile | cut -d':' -f5)
#	[ -z $(ps -eo pid,cmd | grep $nfq | grep -v grep) ] && [ -z $nfqpid ] && (echo 路由过滤进程未成功运行，详情见日志文件 && voff && exit 1)
done
#echo 路由过滤进程号： $nfqpid

#检测初始化是否完成
nfqresult=$(grep nfqresult $logfile | cut -d':' -f5)
while [ -z $nfqresult ]
do
	echo -n .
	sleep 0.5
#检测路由过滤程序是否正常运行
	if [ -z $(ps -eo pid | grep $nfqpid) ]
	then
		nfqresult=$(grep nfqresult $logfile | cut -d':' -f5)
		[ -z $nfqresult ] && echo 路由过滤进程意外退出，错误详情见日志文件 && voff && exit 1
	fi
	nfqresult=$(grep nfqresult $logfile | cut -d':' -f5)
done
echo .

#检测路由过滤进程结果
if [ "$nfqresult" = "SUCCESS" ]
then
	echo 已启动路由过滤进程，下线请运行voff程序
else
	echo 路由过滤进程运行失败，错误详情见日志文件 && voff && exit 1
fi

wait

exit 0